{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fc9c30b6cb4cd81e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:32:56.882808Z",
     "start_time": "2025-05-08T01:32:56.879634Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i: 0, obj: {'id': 1, 'instruction': '', 'input': '好的。现在请你将这个文本中的所有的逗号都替换成空格。', 'output': '好的，请稍等一下，现在我会将文本中的所有逗号替换为空格。处理后文本为：\"这是一个句子 目的是看看是否可以正确地从这个句子中删除关键词。\"。处理结果如何？', 'history': [['给定一段文本和关键词列表，删除文本中包含所有给定关键词的子字符串。\\n文本：\"这是一个测试句子，目的是看看模型是否可以正确地从这个句子中删除关键词。\"\\\\n关键词列表：[‘测试’，‘模型’]', '删除包含所有给定关键词的子字符串后，文本变为：\"这是一个句子，目的是看看是否可以正确地从这个句子中删除关键词。\"']], 'language': 'chinese', 'data_source': 'https://huggingface.co/datasets/BelleGroup/train_3.5M_CN', 'input_len': 59, 'output_len': 66, 'num_utter': 2, 'type': 31, 'type_keyword': ['字符串', '代码', '函数', '编写', '实现', '给定', '使用', '输入', '文本', '程序']}\n",
      "i: 1, obj: {'id': 2, 'instruction': '', 'input': '帮我回答一道历史题目。清朝时期的八旗共有多少旗人？', 'output': '清朝时期八旗旗人总数约为200万人左右，其中正黄旗、正蓝旗、正白旗、正红旗的人数较多，其他旗的人数较少。', 'history': [['写一个关于秋天的诗吧。', '红黄绿交织，田野金黄色。风吹枫叶落，人在秋天慢步行。'], ['给我推荐一些好听的摇滚歌曲。', \"摇滚歌曲推荐：AC/DC的Back in Black，Guns N' Roses的Sweet Child O' Mine，Rolling Stones的Satisfaction，Led Zeppelin的Stairway to Heaven，Nirvana的Smells Like Teen Spirit等。\"], ['计算一下2的100次方。', '2的100次方等于1.267650600228229401496703205376e+30，约等于1.27乘以10的30次方。']], 'language': 'chinese', 'data_source': 'https://huggingface.co/datasets/BelleGroup/train_3.5M_CN', 'input_len': 15, 'output_len': 73, 'num_utter': 4, 'type': 11, 'type_keyword': ['生成', '诗歌', '主题', '爱情', '创作', '描述', '歌词', '表达', '歌曲', '有关']}\n",
      "i: 2, obj: {'id': 3, 'instruction': '', 'input': '嗯，谢谢你介绍的做法很详细，但我不喜欢吃鸡蛋，有没有其他菜做法能介绍一下？', 'output': '当然，你可以试试酸辣土豆丝这道菜。\\n材料：\\n土豆2个、红椒1个、青椒1个、大葱1根、醋、生抽、盐、鸡精、料酒\\n做法：\\n1.土豆去皮，切成丝；红椒和青椒切成细丝；大葱切段备用。\\n2.热锅凉油，油热后放入土豆丝，煸炒至变软。\\n3.倒入红椒、青椒和大葱段，继续煸炒至熟。\\n4.加入适量的盐、鸡精、料酒和生抽，翻炒均匀。\\n5.最后，加入适量的醋，翻炒均匀即可。\\n小贴士：\\n1. 土豆切丝时，可以放入淡盐水中泡一下，这样可以去除多余的淀粉。\\n2. 煮土豆丝时，不要煮得太久，以免烂糊。\\n3. 加入醋的时候，根据自己的口味多少来进行调节，一般来说，盐与醋的比例为1:1。\\n4. 如果喜欢辣味可以加入一些干辣椒丝。\\n希望你会喜欢这道酸辣土豆丝！', 'history': [['介绍一道好吃的家常菜的做法', '番茄炒蛋\\n材料：\\n鸡蛋3个、番茄1个、油、盐、糖、水淀粉\\n做法：\\n1.番茄洗净切成小块；鸡蛋打入碗中搅匀备用。\\n2.热锅凉油，油热后放入番茄翻炒。\\n3.番茄煮软后放盐，糖调味，再倒入打好的鸡蛋液，翻炒均匀。\\n4.鸡蛋凝固后关火。\\n5.加入半碗水，大火煮开。\\n6.用水淀粉勾芡，装盘即可。\\n小贴士：\\n1. 番茄不能切得太细，否则炒出来就不太好看了。\\n2. 在调味时，糖的分量也很重要，可以根据自己的口味来调节。\\n3. 水淀粉勾芡的比例是：水和淀粉的比例大概是5:1。\\n4. 煮开之后，记得要把水淀粉慢慢倒入，同时不断地搅拌，以免结块。\\n5. 最后装盘时可以点缀一些绿色蔬菜，既好看又好吃。']], 'language': 'chinese', 'data_source': 'https://huggingface.co/datasets/BelleGroup/train_3.5M_CN', 'input_len': 25, 'output_len': 304, 'num_utter': 2, 'type': 47, 'type_keyword': ['制作', '食谱', '包括', '描述', '步骤', '烹饪', '提供', '材料', '食材', '菜谱']}\n",
      "i: 3, obj: {'id': 4, 'instruction': '', 'input': '请描述一下如何正确规划个人理财。', 'output': '正确规划个人理财需要以下几个步骤：\\n1.了解自己的财务状况。这包括收入、支出、资产和负债等信息。了解自己的财务状况可以帮助人们更好地制定财务计划。\\n2.设定财务目标。需要考虑短期目标和长期目标，例如以年为单位设定的支出计划、购房、购车等的长期目标。\\n3.制定预算计划。在了解自己的财务状况并设定财务目标后，需要制定一个预算计划。这可以帮助人们控制支出、节省开支并达到财务目标。\\n4.理性投资和储蓄。人们可以投资于股票、基金、房产或其他投资渠道以实现财务目标。但在投资前需了解相关知识并进行风险评估。同时还应储蓄一定金额，以应对突发事件或为达成某些目标做准备。\\n5.审时度势，合理调整。财务计划需要不断地审时度势，根据实际情况做出调整，以达到最终的财务目标。需要注意财务状况的变化、投资的收益和风险等因素。\\n通过以上五个步骤，人们可以做到合理规划个人理财，掌握自己的财务命运，更好地实现自己的财务目标。', 'history': [], 'language': 'chinese', 'data_source': 'https://huggingface.co/datasets/BelleGroup/train_3.5M_CN', 'input_len': 16, 'output_len': 400, 'num_utter': 1, 'type': 26, 'type_keyword': ['提供', '建议', '问题', '提高', '方法', '帮助', '提出', '进行', '解决', '给出']}\n",
      "i: 4, obj: {'id': 5, 'instruction': '', 'input': '描述一下天堂和地狱的生态系统和环境。', 'output': '天堂和地狱被认为是灵性信仰中关于死后世界的两种不同概念。然而，它们的生态系统和环境都是具有类似特征的极端不同的地方。以下是我对天堂和地狱的生态系统和环境的描述。\\n天堂的生态系统和环境:\\n天堂被描绘为一个美丽、平静、和谐的地方，类似于一片无垢的花园。天堂的生态系统和环境的特征包括:\\n1. 充满和平和爱的氛围。这是一个没有恐惧、痛苦、疾病和死亡的地方。\\n2. 色彩缤纷，充满生机。这是一个绿树成荫、花团锦簇的地方，充满生机和活力。\\n3. 各种生物和动物和谐共存。天使、圣人和各种动物和谐相处，生态系统中没有互相侵害或抢夺资源。\\n4. 充满清新气息的空气。没有污染、烟雾或其他有害物质，空气中充满清新芬芳的气息。\\n5. 物质丰富的环境。天堂中生活着满足需求和愿望的人们，他们拥有一切所需的物质资源，而且没有匮乏、浪费或不公平。\\n地狱的生态系统和环境:\\n地狱被描绘为阴暗、恐怖、嘈杂和可怕的地方。地狱的生态系统和环境的特征包括:\\n1. 充满痛苦和折磨的氛围。这是一个充满恐惧、悔恨和痛苦的地方，全是罪恶的味道。\\n2. 火焰和烈火环绕。地狱中有燃烧的火焰和烈火，许多受罚者被投入火坑中痛苦折磨。\\n3. 恶魔和妖魔横行。地狱中有恶魔、妖怪等可怕的生物，它们在无休止的受苦中享受着自己的又一场比赛。\\n4. 污染和恶臭的气味。地狱中到处都是恶臭和污染，没有清新的气息。\\n5. 没有物质资源。地狱中生活着被惩罚的人们不可能拥有任何物质财富，地狱环境充满了无尽的贫困、饥饿和疾病。\\n综上所述，天堂和地狱是两个完全不同的地方，它们的生态系统和环境反映了它们的性质，体现了人类对不同阶段的死后生命的不同想象和信仰。', 'history': [], 'language': 'chinese', 'data_source': 'https://huggingface.co/datasets/BelleGroup/train_3.5M_CN', 'input_len': 18, 'output_len': 696, 'num_utter': 1, 'type': 23, 'type_keyword': ['解释', '描述', '概念', '提供', '包括', '说明', '给出', '应用', '介绍', '原理']}\n"
     ]
    }
   ],
   "source": [
    "import jsonlines\n",
    "\n",
    "# 查看JSONL文件的前几行\n",
    "file_path = 'dataset/aa/deepctrl-sft-custom_data/sft_data_zh.jsonl'\n",
    "\n",
    "with jsonlines.open(file_path) as reader:\n",
    "    for i, obj in enumerate(reader):\n",
    "        print(f'i: {i}, obj: {obj}')\n",
    "        if i >= 4:  # 只打印前5行\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b3a04bdc",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_total_lines(file_path):\n",
    "    with open(file_path, 'rb') as f:  # 使用二进制模式避免编码问题\n",
    "        return sum(1 for _ in f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "01456eeb",
   "metadata": {},
   "outputs": [],
   "source": [
    "total_lines = get_total_lines(file_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0a5ba1ed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total lines in dataset/aa/deepctrl-sft-data/sft_data_zh.jsonl: 11381621\n",
      "11381621\n"
     ]
    }
   ],
   "source": [
    "print(f\"Total lines in {file_path}: {total_lines}\")\n",
    "print(total_lines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "46e06163fa10d48e",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:21:25.592835Z",
     "start_time": "2025-05-08T01:20:47.047394Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\conda\\a311\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "import csv\n",
    "import itertools\n",
    "import re\n",
    "import json\n",
    "import jsonlines\n",
    "import psutil\n",
    "import ujson\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from transformers import AutoTokenizer\n",
    "from datasets import load_dataset\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cf24e198",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:21:25.597807Z",
     "start_time": "2025-05-08T01:21:25.595840Z"
    }
   },
   "outputs": [],
   "source": [
    "bos_token = \"<s>\"\n",
    "eos_token = \"</s>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "515b4daf",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:21:25.613401Z",
     "start_time": "2025-05-08T01:21:25.599317Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "词表大小: 6400\n"
     ]
    }
   ],
   "source": [
    "tokenizer = AutoTokenizer.from_pretrained(\"model\", use_fast=False)\n",
    "print(f'词表大小: {len(tokenizer)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "79608dd9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:28:34.961582Z",
     "start_time": "2025-05-08T01:21:25.757072Z"
    }
   },
   "outputs": [],
   "source": [
    "from tqdm import tqdm\n",
    "\n",
    "def sft_process(contain_history=False):\n",
    "    file_name = 'sft_data.csv' if contain_history else 'sft_data_single.csv'\n",
    "\n",
    "\n",
    "    def chinese_ratio(text):\n",
    "        chinese_chars = re.findall(r'[\\u4e00-\\u9fa5]', text)\n",
    "        return len(chinese_chars) / len(text) if text else 0\n",
    "\n",
    "    def process_and_write_data(data):\n",
    "        q_lst, a_lst, history_lst = [], [], []\n",
    "\n",
    "        for per in data:\n",
    "            history, q, a = per['history'], per['q'], per['a']\n",
    "\n",
    "            if (contain_history and not history) or not q or not a:\n",
    "                continue\n",
    "            if len(q) < 10 or len(a) < 5:\n",
    "                continue\n",
    "            if len(q) > 256 or len(a) > 256:\n",
    "                continue\n",
    "            if not(chinese_ratio(q) > 0.9 and chinese_ratio(a) > 0.9):\n",
    "                continue\n",
    "\n",
    "            q_lst.append(q)\n",
    "            a_lst.append(a)\n",
    "            history_lst.append(history if contain_history else [])\n",
    "\n",
    "        df = pd.DataFrame({'history': history_lst, 'q': q_lst, 'a': a_lst})\n",
    "        df.to_csv(f'dataset/{file_name}', mode='a', header=False, index=False, lineterminator='\\r\\n', escapechar='\\\\', quoting=csv.QUOTE_NONE)\n",
    "\n",
    "    chunk_size = 1000\n",
    "    data = []\n",
    "\n",
    "    with open(f'dataset/{file_name}', mode='w', encoding='utf-8') as f:\n",
    "        f.write('history,q,a\\n')\n",
    "\n",
    "    sft_datasets = ['dataset/aa/deepctrl-sft-custom_data/sft_data_zh.jsonl']\n",
    "    for path in sft_datasets:\n",
    "        total_lines = get_total_lines(path)\n",
    "\n",
    "        with jsonlines.open(path) as reader:\n",
    "            with tqdm(total=total_lines, desc=\"processing lines\") as pbar:\n",
    "                for idx, obj in enumerate(reader):\n",
    "                    try:\n",
    "                        data.append({'history': obj.get('history', ''), 'q': obj.get('input', '') + obj.get('q', ''), 'a': obj.get('output', '') + obj.get('a', '')})\n",
    "                        if len(data) >= chunk_size:\n",
    "                            process_and_write_data(data)\n",
    "                            data = []\n",
    "                            pbar.update(chunk_size)\n",
    "                    except jsonlines.InvalidLineError as e:\n",
    "                        print(f'skip line {idx}: {e}')\n",
    "                        continue\n",
    "                if data:\n",
    "                    process_and_write_data(data)\n",
    "                    pbar.update(len(data))\n",
    "    print(\"数据处理完成\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "da4bf0034d14556",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-08T01:16:21.451602Z",
     "start_time": "2025-05-08T01:16:21.399602Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "processing lines: 100%|██████████| 11381621/11381621 [02:08<00:00, 88407.01it/s] "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据处理完成\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "sft_process(contain_history=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "c263f340b14a67b7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    history                                                  q  \\\n",
      "0        []                             请从这篇文章中提取出关于分类垃圾的解决方案。   \n",
      "1        []                    根据以下文本，对此事件进行分类：中国队在足球比赛中赢得了冠军。   \n",
      "2        []                                       请告诉我什么是机器学习。   \n",
      "3        []                                      请解释一下什么是人工智能。   \n",
      "4        []                                      对给定的命题进行真假判断\\   \n",
      "5  梦是一种真实经验  这个命题是错误的。尽管梦境中的经验可以让我们产生强烈的情感反应，但梦并不是一种真实经验，它是...   \n",
      "6        []       嗯，这些地方都很不错，但是我还想找一些可以体验当地文化和风俗的地点，你有什么好的建议吗？   \n",
      "7        []                                    请简要概括一下这篇文章的主旨。   \n",
      "8        []                                      请从文章中提取汉服的历史。   \n",
      "9        []                        我想让主菜中的北京烤鸭加入传统的花雕酒口味，能做到吗？   \n",
      "\n",
      "                                                   a  \n",
      "0  文章中提到的第二个方面——分类垃圾，是解决垃圾污染的有效措施之一。垃圾分类是指将生活垃圾按照...  \n",
      "1  这个事件可以被分类为体育比赛。具体地，中国队在足球比赛中致胜并赢得了冠军。由此可以推断出，这...  \n",
      "2  机器学习是一种人工智能技术，它使用算法和数学模型，让计算机自动地从数据中学习，并根据这些数据...  \n",
      "3  人工智能是一种模拟人类智能的技术和方法。它的发展包括机器学习、自然语言处理、计算机视觉等技术...  \n",
      "4                                                NaN  \n",
      "5                                                NaN  \n",
      "6  如果你想要更深入地了解当地文化和风俗，可以考虑参加一些游学活动，比如参观当地的博物馆、参加民...  \n",
      "7  这篇散文主要讨论了人工智能的发展及其可能面临的挑战和风险。尽管人工智能在各个领域中具备着极高...  \n",
      "8                  汉服是中国传统服饰文化中的一种，源自汉朝，至今已有两千余年的历史。  \n",
      "9  可以的，我们可以加入适量的花雕酒来烤制北京烤鸭，这样不仅能保持传统的口味，还能增加创意和个性...  \n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "file_path = 'dataset/sft_data_single.csv'\n",
    "df = pd.read_csv(file_path, nrows=10)\n",
    "print(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7baa63a9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "文件大小: 320.60 MB\n",
      "文件大小: 16396.53 MB\n"
     ]
    }
   ],
   "source": [
    "# 计算文件大小\n",
    "import os\n",
    "file_size = os.path.getsize(file_path)\n",
    "print(f\"文件大小: {file_size / (1024 * 1024):.2f} MB\")  # 转换为MB并格式化输出\n",
    "\n",
    "file_size = os.path.getsize(\"dataset/aa/deepctrl-sft-custom_data/sft_data_zh.jsonl\")\n",
    "print(f\"文件大小: {file_size / (1024 * 1024):.2f} MB\")  # 转换为MB并格式化输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ec0f5a4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
